//  
//  Sprawdzacz
//  
//  Author:
//       Grzegorz Żur <grzegorz.zur@gmail.com>
// 
//  Copyright (c) 2010-2011 Grzegorz Żur
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Text.RegularExpressions;

namespace Sprawdzacz
{

	public class PESEL : Validator
	{
		public const string NAME = "PESEL";
		
		private static readonly Regex PATTERN = new Regex ("^[0-9]{11}$");

		private const int MINUEND = 10;

		private const int DIVIDER = 10;

		private const int CHECKSUM_POSITION = 10;

		private static readonly int[] WEIGHTS = { 1, 3, 7, 9, 1, 3, 7, 9, 1, 3, 0 };

		public PESEL () : base(NAME)
		{
		}

		public override Validation Validate (string number)
		{
			number = Normalize (number);
			if (!PATTERN.IsMatch (number))
				return new Validation (false, Name, number, null);
			
			int[] digits = Numbers (number);
			int checksum = digits[CHECKSUM_POSITION];
			int sum = Sum (WEIGHTS, digits);
			int reminder = (MINUEND - sum % DIVIDER) % DIVIDER;
			if (reminder != checksum)
				return new Validation (false, Name, number, null);
			
			int century = 0;
			int month = 10 * digits[2] + digits[3];
			if (month >= 81 && month <= 92) {
				month -= 80;
				century = 1800;
			} else if (month >= 1 && month <= 12) {
				month -= 0;
				century = 1900;
			} else if (month >= 21 && month <= 32) {
				month -= 20;
				century = 2000;
			} else if (month >= 41 && month <= 52) {
				month -= 40;
				century = 2100;
			} else if (month >= 61 && month <= 72) {
				month -= 60;
				century = 2200;
			}
			int year = century + 10 * digits[0] + digits[1];
			int day = 10 * digits[4] + digits[5];
			int seq = 1000 * digits[6] + 100 * digits[7] + 10 * digits[8] + digits[9];
			string sex = digits[9] % 2 == 0 ? "kobieta" : "mężczyzna";
			
			DateTime date;
			try {
				date = new DateTime (year, month, day);
			} catch (ArgumentOutOfRangeException) {
				return new Validation (false, Name, number, null);
			}
			
			string message = string.Format ("{0} {1} {2} {3:0000}", number, sex, date.ToShortDateString (), seq);
			return new Validation (true, Name, number, message);
		}
		
	}
	
}
